﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "GnufBase.h"
#include "GnufUiCommonDef.h"
#include "GnufINotificationCenterEventArgs.h"
#include "GnufComponentDeclaration.h"
#include "GnufIAssetDisplay.h"
#include "GnufIProjectDisplay.h"
#include "GnufIDisplayManager.h"

namespace gnuf {

    class IDisplayManager;
    class IAssetDisplay;
    class IProjectDisplay;

    class GNUF_BASE_EXPORT AssetDisplayEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(AssetDisplayEventArgs, INotificationCenterEventArgs)
    public:
        enum class EType : std::uint8_t
        {
            eUnknown,

            // What done...
            eCreated,
            eActivated,
            eDeactivated,
            eClosed,
            eRenamed,
            ePreShown,
            ePreHidden
        };

        AssetDisplayEventArgs(AssetDisplayEventArgs::EType, IAssetDisplay *);

        AssetDisplayEventArgs::EType type() const { return m_type; }
        IAssetDisplay * assetDisplay() { return m_wpAssetDisplay.IsValid() ? m_wpAssetDisplay.Get() : nullptr; }

    private:
        const AssetDisplayEventArgs::EType m_type;
        gcmp::WeakPtr<IAssetDisplay> m_wpAssetDisplay;
    };

    class GNUF_BASE_EXPORT ProjectDisplayEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ProjectDisplayEventArgs, INotificationCenterEventArgs)
    public:
        enum class EType : std::uint8_t
        {
            eUnknown,

            // What done...
            eCreated,
            eActivated,
            eDeactivated,
            ePreClose,
            eClosed,
            eRenamed,
            eAssetDisplayPostClosed,
            eAssetDisplayPostHolded,
            eAssetDisplayPostUnholded
        };

        ProjectDisplayEventArgs(ProjectDisplayEventArgs::EType, IProjectDisplay *);

        ProjectDisplayEventArgs::EType type() const { return m_type; }
        IProjectDisplay * projectDisplay(){ return m_wpProjectDisplay.IsValid() ? m_wpProjectDisplay.Get() : nullptr; }

    private:
        const ProjectDisplayEventArgs::EType m_type;
        gcmp::WeakPtr<IProjectDisplay> m_wpProjectDisplay;
    };

    class GNUF_BASE_EXPORT DisplayManagerEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(DisplayManagerEventArgs, INotificationCenterEventArgs)

    public:
        enum class EType : std::uint8_t
        {
            eUnknown,

            // What done...
            eShowAll
        };

        DisplayManagerEventArgs(DisplayManagerEventArgs::EType, IDisplayManager *);

        DisplayManagerEventArgs::EType type() const { return m_type; }
        IDisplayManager * displayManager() { return m_wpDisplayManager.IsValid() ? m_wpDisplayManager.Get() : nullptr; }

    private:
        const DisplayManagerEventArgs::EType m_type;
        gcmp::WeakPtr<IDisplayManager> m_wpDisplayManager;
    };

    class GNUF_BASE_EXPORT UiViewEventArgs final 
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(UiViewEventArgs, INotificationCenterEventArgs)
    public:
        enum class EType : std::uint8_t
        {
            eUnknown,

            // What done...
            eCreated,
            eActivated,
            eDeactivated,
            eClosed,
            eRenamed,

            // Do what...
            eActivate,
            eClose
        };

        UiViewEventArgs(UiViewEventArgs::EType,
            int uiDocId, int uiViewId, 
            std::uint64_t uiViewWinId = 0, 
            const std::wstring & caption = L"",
            const std::wstring & fullCaption = L"");

        inline UiViewEventArgs::EType type() const { return m_type; }
        inline int uiDocId() const { return m_uiDocId; }
        inline std::uint64_t uiViewWinId() const { return m_uiViewWinId; }
        inline int uiViewId() const { return m_uiViewId; }
        inline const std::wstring & caption() const { return m_caption; }
        inline const std::wstring& fullCaption() const { return m_fullCaption; }

    private:
        const UiViewEventArgs::EType m_type;
        const int m_uiDocId;
        const int m_uiViewId;
        const std::uint64_t m_uiViewWinId;
        const std::wstring m_caption;
        const std::wstring m_fullCaption;
    };

    class GNUF_BASE_EXPORT UiDocumentEventArgs final 
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(UiDocumentEventArgs, INotificationCenterEventArgs)
    public:
        enum class EType : std::uint8_t
        {
            eUnknown,

            // What done...
            eActivated,
            eDeactivated,
            eClosed,

            // Do what...
            eClose
        };

        UiDocumentEventArgs(UiDocumentEventArgs::EType, 
            int uiDocId,
            const std::wstring & caption = L"");

        inline UiDocumentEventArgs::EType type() const { return m_type; }
        inline int uiDocId() const { return m_uiDocId; }
        inline const std::wstring & caption() const { return m_caption; }

    private:
        const UiDocumentEventArgs::EType m_type;
        const int m_uiDocId;
        const std::wstring m_caption;
    };

    class GNUF_BASE_EXPORT WorkStagePostInitializedEventArgs
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(WorkStagePostInitializedEventArgs, INotificationCenterEventArgs)
    public:
        WorkStagePostInitializedEventArgs();
    };
    class GNUF_BASE_EXPORT WorkStagePreUninitializedEventArgs
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(WorkStagePreUninitializedEventArgs, INotificationCenterEventArgs)
    public:
        WorkStagePreUninitializedEventArgs();
    };

    class WorkBench;
    class GNUF_BASE_EXPORT WorkStageSwitchedEventArgs
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(WorkStageSwitchedEventArgs, INotificationCenterEventArgs)
    protected:
        WorkStageSwitchedEventArgs(WorkBench *, EWorkStage, EWorkStage);
    public:
        WorkBench * workBench() { return m_workBench; }
        const EWorkStage oldWorkStage() const { return m_oldWorkStage; }
        const EWorkStage newWorkStage() const { return m_newWorkStage; }

    private:
        WorkBench * m_workBench;
        const EWorkStage m_oldWorkStage, m_newWorkStage;
    };
    class GNUF_BASE_EXPORT WorkStagePreSwitchedEventArgs final
        : public WorkStageSwitchedEventArgs
    {
        DEFINE_CAST_DERIVED(WorkStagePreSwitchedEventArgs, WorkStageSwitchedEventArgs)
    public:
        WorkStagePreSwitchedEventArgs(WorkBench *, EWorkStage, EWorkStage);
    };
    class GNUF_BASE_EXPORT WorkStagePostSwitchedEventArgs final
        : public WorkStageSwitchedEventArgs
    {
        DEFINE_CAST_DERIVED(WorkStagePostSwitchedEventArgs, WorkStageSwitchedEventArgs)
    public:
        WorkStagePostSwitchedEventArgs(WorkBench *, EWorkStage, EWorkStage);
    };

    class GraphicsCanvas;
    class GNUF_BASE_EXPORT UiViewSeekerEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(UiViewSeekerEventArgs, INotificationCenterEventArgs)

    public:
        UiViewSeekerEventArgs(std::uint64_t);

        const std::uint64_t uiViewWinId() const { return m_uiViewWinId; }
        void setGrapicsCanvas(GraphicsCanvas * gc) { m_graphicsCanvas = gc; }
        GraphicsCanvas * graphicsCanvas() const { return m_graphicsCanvas; }

    private:
        const std::uint64_t m_uiViewWinId;
        GraphicsCanvas * m_graphicsCanvas;
    };

    class GNUF_BASE_EXPORT ConfigurationsEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ConfigurationsEventArgs, INotificationCenterEventArgs)
    public:
        ConfigurationsEventArgs();

        inline void setConfigurationsDirectory(const std::wstring & dir) {
            m_configurationsDirectory = dir;
        }
        inline const std::wstring & configurationsDirectory() const {
            return m_configurationsDirectory;
        }
    private:
        std::wstring m_configurationsDirectory;
    };

    class GNUF_BASE_EXPORT MinorConfigurationsEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(MinorConfigurationsEventArgs, INotificationCenterEventArgs)
    public:
        enum EConfigurationType { eMainTitleBar, eMainToolbar };
        MinorConfigurationsEventArgs(EConfigurationType);

        inline EConfigurationType configurationType() const {
            return m_configurationType;
        }

        inline void setFilePathes(const std::list< std::wstring > & pathes) {
            m_filePathes = pathes;
        }
        inline void addFilePath(const std::wstring & path) {
            m_filePathes.push_back(path);
        }
        inline const std::list< std::wstring > & filePathes() const {
            return m_filePathes;
        }

    private:
        const EConfigurationType m_configurationType;
        std::list< std::wstring > m_filePathes;
    };

    class GNUF_BASE_EXPORT CloseDesktopEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(CloseDesktopEventArgs, INotificationCenterEventArgs)
    public:
        CloseDesktopEventArgs();

        inline void setWantToCloseDesktop(bool wantToCloseDesktop) {
            m_wantToCloseDesktop = wantToCloseDesktop;
        }
        inline bool wantToCloseDesktop() const {
            return m_wantToCloseDesktop;
        }
    private:
        bool m_wantToCloseDesktop;
    };

    class GNUF_BASE_EXPORT PreCloseApplicationEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(PreCloseApplicationEventArgs, INotificationCenterEventArgs)
    public:
        PreCloseApplicationEventArgs();

        inline void setWantToCloseApplication(bool wantToCloseApplication) {
            m_wantToCloseApplication = wantToCloseApplication;
        }
        inline bool wantToCloseApplication() const {
            return m_wantToCloseApplication;
        }
    private:
        bool m_wantToCloseApplication;
    };

    class GNUF_BASE_EXPORT PostCloseApplicationEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(PostCloseApplicationEventArgs, INotificationCenterEventArgs)
    public:
        PostCloseApplicationEventArgs(bool closed) : m_closed(closed) {}
        bool closed() const { return m_closed; }
    private:
        bool m_closed;
    };

    class GNUF_BASE_EXPORT OkCancelEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(OkCancelEventArgs, INotificationCenterEventArgs)
    public:
        OkCancelEventArgs(bool);

        inline bool isOkButtonClicked() const { return m_okButtonClicked; }
        inline bool isCancelButtonClicked() const { return !m_okButtonClicked; }
    private:
        const bool m_okButtonClicked;
    };

    class GNUF_BASE_EXPORT WelcomePanelEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(WelcomePanelEventArgs, INotificationCenterEventArgs)
    public:
        WelcomePanelEventArgs(const gcmp::Any *);

        inline const gcmp::Any * buttonClicked() const { return m_buttonClicked; }
    private:
        const gcmp::Any * m_buttonClicked;
    };

    class ValueInputBase;
    class GNUF_BASE_EXPORT ValueInputChangeEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ValueInputChangeEventArgs, INotificationCenterEventArgs)
    public:
        ValueInputChangeEventArgs(ValueInputBase *);

        inline ValueInputBase * valueInput() const { return m_valueInput; }
    private:
        ValueInputBase * m_valueInput;
    };

    class GNUF_BASE_EXPORT SwitchWorkspaceEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(SwitchWorkspaceEventArgs, INotificationCenterEventArgs)
    public:
        SwitchWorkspaceEventArgs(
            const std::wstring & oldWorkspace,
            const std::wstring & newWorkspace);

        const std::wstring & oldWorkspace() const { return m_oldWorkspace; }
        const std::wstring & newWorkspace() const { return m_newWorkspace; }

        void setApproved(bool approved) { m_approved = approved; }
        bool approved() const { return m_approved; }

    private:
        const std::wstring m_oldWorkspace, m_newWorkspace;
        bool m_approved;
    };

    class IAnnouncementObserver;
    class Announcement;
    class GNUF_BASE_EXPORT AnnouncementEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(AnnouncementEventArgs, INotificationCenterEventArgs)
    public:
        AnnouncementEventArgs(
            gcmp::OwnerPtr<Announcement> &&,
            IAnnouncementObserver * pObserver = nullptr);
        ~AnnouncementEventArgs();
        Announcement * announcement() { return m_announcement.get(); }
        IAnnouncementObserver * observer() const { return m_pObserver; }
    private:
        gcmp::OwnerPtr<Announcement> m_announcement;
        IAnnouncementObserver * m_pObserver = nullptr;
    };

    class Hotkey;
    class GNUF_BASE_EXPORT HotkeysEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(HotkeysEventArgs, INotificationCenterEventArgs)
    public:
        enum class EType { eUnknown, eKeyPress, eSystem };
        explicit HotkeysEventArgs(HotkeysEventArgs::EType type,
            const Hotkey * pHotkeyToBeTriggered = nullptr,
            const std::wstring & text = L"",
            bool canRepeatLastCommand = false);
        
        HotkeysEventArgs::EType type() const { return m_type; }

        const std::wstring & text() const { return m_text; }
        
        bool canRepeatLastCommand() const { return m_canRepeatLastCommand; }

        void enableKeyPressHotkey(bool val) { m_keyPressHotkeyEnabled = val; }
        bool keyPressHotkeyEnabled() const { return m_keyPressHotkeyEnabled; }

        void enableSystemHotkey(bool val) { m_systemHotkeyEnabled = val; }
        bool systemHotkeyEnabled() const { return m_systemHotkeyEnabled; }

        const Hotkey * hotkeyToBeTriggered() const { return m_pHotkeyToBeTriggered; }
    private:
        const HotkeysEventArgs::EType m_type = HotkeysEventArgs::EType::eUnknown;
        const std::wstring m_text;
        const Hotkey * m_pHotkeyToBeTriggered = nullptr;
        bool m_canRepeatLastCommand  = false;
        bool m_keyPressHotkeyEnabled = false; // disable the key press hotkey
        bool m_systemHotkeyEnabled   = true;  //     enable the system hotkey
    };

    class GNUF_BASE_EXPORT HotkeysChangedEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(HotkeysChangedEventArgs, INotificationCenterEventArgs)
    public:
        explicit HotkeysChangedEventArgs(bool isSystem,
            const std::wstring& oldShortcut,
            const std::wstring& newShortcut);

        const std::wstring& oldShortcut() const { return m_oldShortcut; }

        const std::wstring& newShortcut() const { return m_newShortcut; }

        bool isSystem() const { return m_isSystem; }
    private:
        const std::wstring m_oldShortcut;
        const std::wstring m_newShortcut;
        bool m_isSystem = false;
    };

    class GNUF_BASE_EXPORT WindowStateChangedEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(WindowStateChangedEventArgs, INotificationCenterEventArgs)
    public:
        WindowStateChangedEventArgs(int oldQtWindowStates, int newQtWindowStates);
        const int oldQtWindowStates() const { return m_oldQtWindowStates; }
        const int newQtWindowStates() const { return m_newQtWindowStates; }
    private:
        int m_oldQtWindowStates, m_newQtWindowStates;
    };

    class GNUF_BASE_EXPORT MainWindowALiveChangedEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(MainWindowALiveChangedEventArgs, INotificationCenterEventArgs)

    public:
        enum class State
        {
            Creation,
            Destroy
        };
        MainWindowALiveChangedEventArgs(State state) : m_state(state){}
        const State state() const { return m_state; }
    private:
        State m_state;
    };

    class Preferences;
    class GNUF_BASE_EXPORT PreferencesChangedEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(PreferencesChangedEventArgs, INotificationCenterEventArgs)
    public:
        PreferencesChangedEventArgs(const Preferences *);
        const Preferences * preferences() const { return m_preferences; }

        // If don't want to respond immediately, the BNUF does not make any
        // response immediately, until next the application startup.
        void setWantToRespondImmediately(bool value) { m_wantToRespondImmediately = value; }
        bool wantToRespondImmediately() const { return m_wantToRespondImmediately; }
    private:
        const Preferences * m_preferences;
        bool m_wantToRespondImmediately;
    };

    struct ToolDefinitionData;
    class GNUF_BASE_EXPORT ToolDefinitionDataEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ToolDefinitionDataEventArgs, INotificationCenterEventArgs)
    public:
        ToolDefinitionDataEventArgs(const ToolDefinitionData *);
        const ToolDefinitionData * toolDefinitionData() const { return m_toolDefinitionData; }
    private:
        const ToolDefinitionData * m_toolDefinitionData;
    };

    class GNUF_BASE_EXPORT AskIfWantToReplaceArrangementAreaContent final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(AskIfWantToReplaceArrangementAreaContent, INotificationCenterEventArgs)
    public:
        AskIfWantToReplaceArrangementAreaContent(const std::wstring & arrangementAreaContent);
        void setArrangementAreaContent(const std::wstring & val) { m_arrangementAreaContent = val; }
        const std::wstring & arrangementAreaContent() const { return m_arrangementAreaContent; }
    private:
        std::wstring m_arrangementAreaContent;
    };

    class GNUF_BASE_EXPORT AskIfWantToAddArrangementArea final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(AskIfWantToAddArrangementArea, INotificationCenterEventArgs)
    public:
        AskIfWantToAddArrangementArea(bool wantToAdd, const std::wstring & arrangementAreaContent);
        const std::wstring & arrangementAreaContent() const { return m_arrangementAreaContent; }
        void setWantToAdd(bool val) { m_wantToAdd = val; }
        bool wantToAdd() const { return m_wantToAdd; }
    private:
        bool m_wantToAdd;
        const std::wstring & m_arrangementAreaContent;
    };
    class Module;
    class GNUF_BASE_EXPORT ModuleSwitchedEventArgs
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ModuleSwitchedEventArgs, INotificationCenterEventArgs)
    public:
        ModuleSwitchedEventArgs(Module* oldModule, Module* newModule);
        const Module* oldModule() const { return m_pOldModule; }
        const Module* newModule() const { return m_pNewModule; }
    private:
        const Module* m_pOldModule; 
        const Module* m_pNewModule;
    };
    class GNUF_BASE_EXPORT ModulePreSwitchedEventArgs final
        : public ModuleSwitchedEventArgs
    {
        DEFINE_CAST_DERIVED(ModulePreSwitchedEventArgs, ModuleSwitchedEventArgs);
    public:
        ModulePreSwitchedEventArgs(Module*, Module*);
    };
    class GNUF_BASE_EXPORT ModulePostSwitchedEventArgs final
        : public ModuleSwitchedEventArgs
    {
        DEFINE_CAST_DERIVED(ModulePostSwitchedEventArgs, ModuleSwitchedEventArgs);
    public:
        ModulePostSwitchedEventArgs(Module*, Module*);
    };

    class GNUF_BASE_EXPORT DynamicPanelButtonStyleChangedEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(DynamicPanelButtonStyleChangedEventArgs, INotificationCenterEventArgs)
    public:
        DynamicPanelButtonStyleChangedEventArgs(const std::wstring & key, EButtonDisplayStyle eStyle);
        const std::wstring& key() const { return m_dynamicPanelKey; }
        const EButtonDisplayStyle style() const { return m_style; }

        const std::wstring m_dynamicPanelKey = L"";
        const EButtonDisplayStyle m_style = EButtonDisplayStyle::eDefault;
    };

    // 子进程通过SendMessage给主程序发送消息，主程序收到转发广播
    // WindowMessageEventArgs包含消息内容参数
    class GNUF_BASE_EXPORT WindowMessageEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(WindowMessageEventArgs, INotificationCenterEventArgs)

    public:
        WindowMessageEventArgs(WPARAM wParam, LPARAM lParam);
        WPARAM wparam() { return m_wParam; }
        LPARAM lparam() { return m_lParam; }

    private:
        WPARAM m_wParam;
        LPARAM m_lParam;
    };

    class ArrangementArea;
    class GNUF_BASE_EXPORT ArrangementAreaMaskedEventArgs final
        : public INotificationCenterEventArgs
    {
        DEFINE_CAST_DERIVED(ArrangementAreaMaskedEventArgs, INotificationCenterEventArgs)

    public:
        enum class EMasked : std::uint8_t { eNo, eYes, eOverall };
        ArrangementAreaMaskedEventArgs(const ArrangementArea * const, ArrangementAreaMaskedEventArgs::EMasked);
        const ArrangementArea * arrangementArea() const { return m_pArrangementArea; }
        bool isMasked()        const { return (              ArrangementAreaMaskedEventArgs::EMasked::eNo      != m_masked); }
        bool isMaskedOverall() const { return (isMasked() && ArrangementAreaMaskedEventArgs::EMasked::eOverall == m_masked); }
    private:
        const ArrangementArea * const m_pArrangementArea = nullptr;
        const ArrangementAreaMaskedEventArgs::EMasked m_masked = ArrangementAreaMaskedEventArgs::EMasked::eNo; // unmasked
    };
}
